#ifndef WORLDOBJECT_H
#define WORLDOBJECT_H
#include <string>

using namespace std;

class WorldObject
{
protected:
    string type, image;
    int id, x, y, xVelocity, yVelocity;
    static int nextID;

public:
    WorldObject();

    //constructor for static WorldObjects
    WorldObject(string initType, string initImage, int initX, int initY):
        type(initType), image(initImage), x(initX), y(initY) {id = ++nextID;}

    //constructor for dynamic WorldObjects
    WorldObject(string initType, string initImage, int initX, int initY, int initXV, int initYV):
        type(initType), image(initImage), x(initX), y(initY), xVelocity(initXV), yVelocity(initYV) {id = ++nextID;}

    //destructor
    ~WorldObject(){--nextID;}

    string getImage() {return image;}
    int getID() {return id;}

    /*save and load the game; methods that store object data as text, or retrieve object data from text.
    Save will use the hard-coded file path, while load will receive a string value from the Game class.
    This will avoid issues with keeping different objects at the correct line in the savefile.*/
    virtual WorldObject* load() = 0;

    //updates x,y of dynamic objects from velocities
    void move();

    //Multipies Velocities by 1 or -1 as parameters indiciate.
    void bounce(int value);

    //Velocity mutators for PacMan's bounce
    void setXVelocity(int newXV) {xVelocity = newXV;}
    void setYVelocity(int newYV) {yVelocity = newYV;}

    void incYVelocity(int incY);
    void switchXVelocity();
    void switchYVelocity();

    int getXVelocity() {return xVelocity;}
    int getYVelocity() {return yVelocity;}
    int getX() {return x;}
    int getY() {return y;}

    string getType() {return type;}

    bool isEaten();
    void setEaten(bool newValue);
    void movePaddle();
    void updateImage(){}
};

class PacMan : public WorldObject
{

public:
    //index for animation frames
    int imgframe;

    //constructor
    PacMan(string initType, string initImage, int initX, int initY, int initXV, int initYV):
        WorldObject(initType, initImage, initX, initY, initXV, initYV) {}
    //destructor
    ~PacMan(){}

    //instantiates new PacMan from string
    WorldObject* load();
    void updateImage();


};

class Ghost : public WorldObject
{
    //index for animation frames
    int imgframe;

public:
    //constructor
    Ghost(string initType, string initImage, int initX, int initY, int initXV, int initYV):
        WorldObject(initType, initImage, initX, initY, initXV, initYV), imgframe(0) {}
    //destructor
    ~Ghost(){}

    //instantiates new Ghost from string, returns pointer
    WorldObject* load();

};

class Paddle : public WorldObject
{
    //index for animation frames
    int yVelocity;

public:
    //constructor; only moves in Y, so initXV not used.
    Paddle(string initType, string initImage, int initX, int initY, int initYV):
        WorldObject(initType, initImage, initX, initY), yVelocity(initYV) {}
    //destructor
    ~Paddle(){}

    //instantiates new Paddle from string, returns pointer
    WorldObject* load();

};

class Wall : public WorldObject
{
public:
    //uses static constructor
    Wall(string initType, string initImage, int initX, int initY):
        WorldObject(initType, initImage, initX, initY) {}
    //destructor
    ~Wall(){}

    //instantiates new Wall from string, returns pointer
    WorldObject* load();
};

class Dot : public WorldObject
{
public:
    bool eaten;
    //uses static constructor
    Dot(string initType, string initImage, int initX, int initY):
        WorldObject(initType, initImage, initX, initY), eaten(false) {}
    //destructor
    ~Dot(){}

    //check to see if dot is eaten
    bool IsEaten() {return eaten;}


    //instantiates new Dot from string, returns pointer
    WorldObject* load();
    bool isEaten() {return eaten;}
    void setEaten(bool newValue) {eaten = newValue;}
};



#endif // WORLDOBJECT_H
